package com.toKnow.service.impl;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.toKnow.mapper.UserInfoMapper;
import com.toKnow.model.dto.UserRegisterDTO;
import com.toKnow.model.dto.transfer.UserRegisterDTOTransfer;
import com.toKnow.model.entity.UserInfo;
import com.toKnow.service.RegisterService;
import com.toKnow.utils.FormatUtil;
import com.toKnow.utils.JwtActivateUtil;
import com.toKnow.utils.MailUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.List;

@Service
public class RegisterServiceImpl implements RegisterService {

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private Producer captchaProducer;

    @Override
    public Integer isDuplicate(String fieldName, String fieldValue) {
        List<UserInfo> userInfoList = userInfoMapper.selectUsersBySingleAttr(fieldName, fieldValue);
        if(userInfoList.size() == 0){ // 找不到，返回0
            return 0;
        } else {
            for (UserInfo userInfo : userInfoList) {
                if(userInfo.getIsActive() == 1){ // 已激活，返回正数id
                    return userInfo.getId();
                }
            }
            // 未激活，返回第一个id的负数
            return -userInfoList.get(0).getId();
        }
    }

    @Override
    public String checkUsername(String username){
        if(isDuplicate("username", username) > 0){ // 重复
            return "用户名已存在";
        }else{
            return FormatUtil.checkUsername(username);
        }
    }

    @Override
    public String checkUserpwd(String userpwd){
        return FormatUtil.checkUserpwd(userpwd);
    }

    @Override
    public String checkEmail(String email){
        if(isDuplicate("email", email) > 0){ // 重复
            return "用户邮箱已被使用";
        }else{ // 不重复
            return FormatUtil.checkEmail(email);
        }
    }

    @Override
    public void generateCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("image/jpeg");
        //生成验证码
        String capText = captchaProducer.createText();
        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
        //向客户端写出
        BufferedImage bi = captchaProducer.createImage(capText);
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(bi, "jpg", out);
        try {
            out.flush();
        } finally {
            out.close();
        }
    }

    /**
     * 辅助activateUser与registerUser，检查用户名或邮箱是否已被激活
     * 若是则返回1，否则返回0
     */
    private Integer isActive(String fieldName, String fieldValue) {
        List<UserInfo> userInfoList = userInfoMapper.selectUsersBySingleAttr(fieldName, fieldValue);
        if(userInfoList.size() != 0){
            for (UserInfo userInfo : userInfoList) {
                if(userInfo.getIsActive() == 1){
                    return 1;
                }
            }
        }
        return 0;
    }

    /**
     * 辅助registerUser，发送激活邮件
     * 成功返回1，否则返回0
     */
    private boolean sendMail(HttpServletRequest request, UserRegisterDTO userRegisterDTO){
        if(isActive("username", userRegisterDTO.getUsername()) == 1
                || isActive("email", userRegisterDTO.getEmail()) == 1) {
            //用户名或邮箱已存在于被激活的账户中，激活失败
            return false;
        }
        //接收人
        String to = userRegisterDTO.getEmail();
        //邮件内容(有些邮箱不支持html文件格式，所以把链接也显示出来以防万一)
        String activateToken = JwtActivateUtil.sign(userRegisterDTO);
        String activateHref = "http://106.15.190.196/api/register/activate?activateToken=" + activateToken;
        String text = "<html><head></head><body><h1>用户" + userRegisterDTO.getUsername()
                + "注册成功！请在15分钟内点击以下链接免费激活账户</h1>"
                + "<h3><a href='" + activateHref + "' target='_self'>加入toKnow</a></h3></body></html>";
        //邮件标题
        String title = "激活toKnow账号";
        //发送邮件(发件人信息在MailUtil中可以修改)
        return MailUtil.sendMail(to, text, title);
    }

    @Override
    @Transactional
    public String registerUser(HttpServletRequest request, UserRegisterDTO user) {
        Integer isUsernameDuplicate = isDuplicate("username", user.getUsername());
        Integer isEmailDuplicate = isDuplicate("email", user.getEmail());
        int registerSuccess;
        if(!checkUsername(user.getUsername()).equals("") || !checkUserpwd(user.getUserpwd()).equals("")
                || !checkEmail(user.getEmail()).equals("")){ //注册失败
            registerSuccess = 0;
        }else{
            UserInfo userInfo = UserRegisterDTOTransfer.INSTANCE.toUserInfo(user);
            userInfo.setUserpwd(DigestUtils.md5Hex(user.getUserpwd())); //加密密码
            userInfo.setIsActive(0);
            userInfo.setRegisterDate(new Timestamp(System.currentTimeMillis()));
            userInfo.setBirthday(new Date(System.currentTimeMillis()));
            if(isUsernameDuplicate == 0 && isEmailDuplicate == 0){
                registerSuccess = userInfoMapper.insertUser(userInfo);
            }else{
                //用户名优先于邮箱更新，就保证用户名一定是唯一的，但邮箱可能存在于多个未激活的账户中
                userInfo.setId(isUsernameDuplicate < 0 ? -isUsernameDuplicate : -isEmailDuplicate);
                registerSuccess = userInfoMapper.updateUser(userInfo);
            }
        }
        //发送激活邮件
        if(registerSuccess == 0){ //注册失败
            return "注册失败，请检查用户名、邮箱等注册信息！";
        }else{ //注册成功
            boolean success = sendMail(request, user);
            if(success){
                return "";
            } else { //用户邮箱不正确，无法发送邮件
                return "邮件发送失败，请检查邮箱是否正确！";
            }
        }
    }

    @Override
    @Transactional
    public Integer activateUser(String username, String email, String activateCode) {
        if(isActive("username", username) == 1 || isActive("email", email) == 1) {
            //用户名或邮箱已存在于被激活的账户中，激活失败
            return 0;
        }else{
            UserInfo userInfo = userInfoMapper.selectUserByUsernameAndEmail(username, email);
            if(userInfo == null){
                //不存在此条数据
                return 0;
            }else{
                String realActivateCode = userInfo.getActivateCode();
                if(realActivateCode == null || !realActivateCode.equals(activateCode)) {
                    //激活码不匹配，激活失败
                    return 0;
                }else{
                    //激活用户，返回数据库更新结果
                    userInfo.setIsActive(1);
                    return userInfoMapper.updateUser(userInfo);
                }
            }
        }

    }
}
